﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using Client.planet;
using Client.planet.components;

namespace Client.star
{
    /// <summary>
    /// Interaction logic for SolarSystem.xaml
    /// </summary>
    public partial class SolarSystem : WindowOwnerN
    {
        public SolarSystem()
        {
            InitializeComponent();
            Owner = Application.Current.MainWindow;
        }
        public SolarSystem(Planet[] planetArray):this()
        {
            PlanetArray = planetArray;
            CreateSolarSystem(PlanetArray);
            Show();
        }

        private void CreateSolarSystem(Planet[] PlanetArray)
        {
            if(PlanetArray.Length != 0) // TODO: Add Uninhabitable solar system objects here
            {
                for (int i = 0; i < PlanetArray.Length; i++)
                {
                    switch ((int)PlanetArray[i].PlanetIndex)
                    {
                        case 0:
                            Canvas canvas1 = new Canvas();
                            canvas1.Width = canvas1.Height = 100;
                            canvas1.Children.Add(MakePlanet(PlanetArray[i], 100));
                            canvas1.ToolTip = MakeToolTip(canvas1, PlanetArray[i]);
                            canvas1.Tag = PlanetArray[i];

                            Ellipse ellipse1 = new Ellipse();
                            ellipse1.Fill = null;
                            ellipse1.Stroke = Brushes.Yellow;
                            ellipse1.Width = ellipse1.Height = 2000;

                            Canvas.SetLeft(ellipse1, -1655);
                            Canvas.SetTop(ellipse1, -1655);
                            layoutRoot.Children.Add(ellipse1);

                            Canvas.SetLeft(canvas1, 0);
                            Canvas.SetTop(canvas1, 0);
                            layoutRoot.Children.Add(canvas1);
                            break;
                        case 1:
                            Canvas canvas2 = new Canvas();
                            canvas2.Width = canvas2.Height = 100;
                            canvas2.Children.Add(MakePlanet(PlanetArray[i], 100));
                            canvas2.ToolTip = MakeToolTip(canvas2, PlanetArray[i]);
                            canvas2.Tag = PlanetArray[i];

                            Ellipse ellipse2 = new Ellipse();
                            ellipse2.Fill = null;
                            ellipse2.Stroke = Brushes.Yellow;
                            ellipse2.Width = ellipse2.Height = 2000;

                            Canvas.SetLeft(ellipse2, -1555);
                            Canvas.SetTop(ellipse2, -1555);
                            layoutRoot.Children.Add(ellipse2);

                            Canvas.SetLeft(canvas2, 100);
                            Canvas.SetTop(canvas2, 100);
                            layoutRoot.Children.Add(canvas2);
                            break;
                        case 2:
                            Canvas canvas3 = new Canvas();
                            canvas3.Width = canvas3.Height = 100;
                            canvas3.Children.Add(MakePlanet(PlanetArray[i], 100));
                            canvas3.ToolTip = MakeToolTip(canvas3, PlanetArray[i]);
                            canvas3.Tag = PlanetArray[i];

                            Ellipse ellipse3 = new Ellipse();
                            ellipse3.Fill = null;
                            ellipse3.Stroke = Brushes.Yellow;
                            ellipse3.Width = ellipse3.Height = 2000;

                            Canvas.SetLeft(ellipse3, -1455);
                            Canvas.SetTop(ellipse3, -1455);
                            layoutRoot.Children.Add(ellipse3);

                            Canvas.SetLeft(canvas3, 200);
                            Canvas.SetTop(canvas3, 200);
                            layoutRoot.Children.Add(canvas3);
                            break;
                        case 3:
                            Canvas canvas4 = new Canvas();
                            canvas4.Width = canvas4.Height = 100;
                            canvas4.Children.Add(MakePlanet(PlanetArray[i], 100));
                            canvas4.ToolTip = MakeToolTip(canvas4, PlanetArray[i]);
                            canvas4.Tag = PlanetArray[i];

                            Ellipse ellipse4 = new Ellipse();
                            ellipse4.Fill = null;
                            ellipse4.Stroke = Brushes.Yellow;
                            ellipse4.Width = ellipse4.Height = 2000;

                            Canvas.SetLeft(ellipse4, -1355);
                            Canvas.SetTop(ellipse4, -1355);
                            layoutRoot.Children.Add(ellipse4);

                            Canvas.SetLeft(canvas4, 300);
                            Canvas.SetTop(canvas4, 300);
                            layoutRoot.Children.Add(canvas4);
                            break;
                        case 4:
                            Canvas canvas5 = new Canvas();
                            canvas5.Width = canvas5.Height = 100;
                            canvas5.Children.Add(MakePlanet(PlanetArray[i], 100));
                            canvas5.ToolTip = MakeToolTip(canvas5, PlanetArray[i]);
                            canvas5.Tag = PlanetArray[i];

                            Ellipse ellipse5 = new Ellipse();
                            ellipse5.Fill = null;
                            ellipse5.Stroke = Brushes.Yellow;
                            ellipse5.Width = ellipse5.Height = 2000;

                            Canvas.SetLeft(ellipse5, -1255);
                            Canvas.SetTop(ellipse5, -1255);
                            layoutRoot.Children.Add(ellipse5);

                            Canvas.SetLeft(canvas5, 400);
                            Canvas.SetTop(canvas5, 400);
                            layoutRoot.Children.Add(canvas5);
                            break;
                    }
                }
            }
        }

        private object MakeToolTip(FrameworkElement frameworkElement, Planet planet)
        {
            ToolTip tt = new ToolTip();
            ToolTipService.SetShowDuration(frameworkElement, int.MaxValue);
            tt.Content = "Name: " + planet.PlanetName.ToString() + Environment.NewLine +
                "Type: " + planet.PlanetType.ToString() + Environment.NewLine +
                "Size: " + planet.PlanetSize.ToString() + Environment.NewLine +
                "Worth: " + planet.PlanetWorth.ToString() + Environment.NewLine +
                "Moons: " + planet.MoonArray.Length.ToString();

            return tt;
        }

        UIElement MakePlanet(Planet planet, double size)
        {
            Sphere3D sphere3D = new Sphere3D();

            DiffuseMaterial diffuseMaterial = new DiffuseMaterial();
            diffuseMaterial.Brush = new ImageBrush(planet.ImageSource);
            sphere3D.Material = diffuseMaterial;

            Transform3DGroup transform3DGroup = new Transform3DGroup();
            ScaleTransform3D scaleTransform3D = new ScaleTransform3D();
            RotateTransform3D rotateTransform3D = new RotateTransform3D();
            AxisAngleRotation3D axisAngleRotation3d = new AxisAngleRotation3D();
            axisAngleRotation3d.Axis = new Vector3D(0, 1, 0);
            axisAngleRotation3d.Angle = 0;
            rotateTransform3D.Rotation = axisAngleRotation3d;
            transform3DGroup.Children.Add(scaleTransform3D);
            transform3DGroup.Children.Add(rotateTransform3D);
            sphere3D.Transform = transform3DGroup;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 0;
            myDoubleAnimation.To = 360;
            myDoubleAnimation.Duration = new Duration(TimeSpan.Parse("0:0:10"));
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            axisAngleRotation3d.BeginAnimation(AxisAngleRotation3D.AngleProperty, myDoubleAnimation);

            Viewport3D viewport3D = new Viewport3D();
            viewport3D.Width = viewport3D.Height = size;
            viewport3D.ClipToBounds = false;
            RenderOptions.SetEdgeMode(viewport3D, VideoOptions.EdgeMode);

            PerspectiveCamera perspectiveCamera = new PerspectiveCamera();
            perspectiveCamera.Position = new Point3D(0, 0, -4 * (Math.Abs(((int)planet.PlanetSize) - 5))); // @PlanetSize enum@
            perspectiveCamera.LookDirection = new Vector3D(0, 0, 1);
            perspectiveCamera.FieldOfView = 30;
            perspectiveCamera.UpDirection = new Vector3D(0, 1, 0);
            viewport3D.Camera = perspectiveCamera;

            DirectionalLight directionalLight = new DirectionalLight();
            directionalLight.Color = Colors.White;
            directionalLight.Direction = new Vector3D(-1, -1, 1);
            ModelVisual3D modelVisual3D1 = new ModelVisual3D();
            modelVisual3D1.Content = directionalLight;

            #region Scale on mouse over effect
            string scaleEffectName = "scale" + " " + planet.PlanetName;
            scaleEffectName = scaleEffectName.Replace(" ", "_");
            scaleEffectName = scaleEffectName.Replace("'", string.Empty);
            RegisterName(scaleEffectName, scaleTransform3D);

            double scale;
            switch ((int)planet.PlanetSize) // @PlanetSize enum@
            {
                case 0:
                    scale = 5;
                    break;
                case 1:
                    scale = 4;
                    break;
                case 2:
                    scale = 3;
                    break;
                case 3:
                    scale = 2;
                    break;
                case 4:
                    scale = 1.5;
                    break;
                default:
                    scale = 1;
                    break;
            }

            DoubleAnimation doubleAnimationX1 = new DoubleAnimation();
            doubleAnimationX1.To = scale;
            doubleAnimationX1.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationX1, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationX1, new PropertyPath(ScaleTransform3D.ScaleXProperty));

            DoubleAnimation doubleAnimationY1 = new DoubleAnimation();
            doubleAnimationY1.To = scale;
            doubleAnimationY1.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationY1, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationY1, new PropertyPath(ScaleTransform3D.ScaleYProperty));

            DoubleAnimation doubleAnimationZ1 = new DoubleAnimation();
            doubleAnimationZ1.To = scale;
            doubleAnimationZ1.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationZ1, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationZ1, new PropertyPath(ScaleTransform3D.ScaleZProperty));

            DoubleAnimation doubleAnimationX2 = new DoubleAnimation();
            doubleAnimationX2.To = 1;
            doubleAnimationX2.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationX2, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationX2, new PropertyPath(ScaleTransform3D.ScaleXProperty));

            DoubleAnimation doubleAnimationY2 = new DoubleAnimation();
            doubleAnimationY2.To = 1;
            doubleAnimationY2.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationY2, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationY2, new PropertyPath(ScaleTransform3D.ScaleYProperty));

            DoubleAnimation doubleAnimationZ2 = new DoubleAnimation();
            doubleAnimationZ2.To = 1;
            doubleAnimationZ2.Duration = new Duration(TimeSpan.Parse("0:0:2"));
            Storyboard.SetTargetName(doubleAnimationZ2, scaleEffectName);
            Storyboard.SetTargetProperty(doubleAnimationZ2, new PropertyPath(ScaleTransform3D.ScaleZProperty));

            Storyboard storyboard1 = new Storyboard();
            storyboard1.Children.Add(doubleAnimationX1);
            storyboard1.Children.Add(doubleAnimationY1);
            storyboard1.Children.Add(doubleAnimationZ1);

            Storyboard storyboard2 = new Storyboard();
            storyboard2.Children.Add(doubleAnimationX2);
            storyboard2.Children.Add(doubleAnimationY2);
            storyboard2.Children.Add(doubleAnimationZ2);

            viewport3D.MouseEnter += delegate(object sender, MouseEventArgs e)
            {
                storyboard1.Begin(this);
            };

            viewport3D.MouseLeave += delegate(object sender, MouseEventArgs e)
            {
                storyboard2.Begin(this);
            };
            #endregion

            #region Light on select effect
            AmbientLight ambientLight = new AmbientLight();
            ambientLight.Color = Color.FromArgb(255, 100, 100, 100);
            ModelVisual3D modelVisual3D2 = new ModelVisual3D();
            modelVisual3D2.Content = ambientLight;

            viewport3D.Focusable = true;
            viewport3D.MouseDown += delegate(object sender, MouseButtonEventArgs e)
            {
                if (!viewport3D.Children.Contains(modelVisual3D2))
                    viewport3D.Children.Add(modelVisual3D2);
                viewport3D.Focus();
            };
            viewport3D.LostFocus += delegate(object sender, RoutedEventArgs e)
            {
                viewport3D.Children.Remove(modelVisual3D2);
                e.Handled = true;
            }; 
            #endregion

            viewport3D.Children.Add(sphere3D);
            viewport3D.Children.Add(modelVisual3D1);

            return viewport3D;
        }

        Planet[] planetArray;

        public Planet[] PlanetArray
        {
            get { return planetArray; }
            set { planetArray = value; }
        }

        private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (e.OriginalSource is Viewport3D)
            {
                Canvas canvas = (Canvas)((Viewport3D)e.OriginalSource).Parent;//(Canvas)sender;
                Planet planet = (Planet)canvas.Tag;

                PlanetView planetView = new PlanetView(planet);
                planetView.Owner = this;
                planetView.Show();
            }
            e.Handled = true;
        }        
    }
}
